#ifndef __CAN_CONTROLLER__H
#define __CAN_CONTROLLER__H

#include "aos/kernel.h"
#include "fsl_flexcan.h"

#define CHECK_ERR(a, str, goto_tag, ...)                                                \
    do                                                                                  \
    {                                                                                   \
        if (!(a))                                                                       \
        {                                                                               \
            printf("%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__);         		\
            goto goto_tag;                                                              \
        }                                                                               \
    } while (0)

#define CHECK_NULL(a, str, goto_tag, ...)   CHECK_ERR(a, str, goto_tag, ##__VA_ARGS__)
#define CHECK_NZERO(a, str, goto_tag, ...)  CHECK_ERR(0U == (a), str, goto_tag, ##__VA_ARGS__)

/**
 * @brief       初始化 CAN 列表中所列CAN接口
 * @return      bool                是否初始化成功
 */
extern bool can_controller_init(void);
/**
 * @brief       添加接收节点（指定过滤器，指定消息接收队列）
 * @param[in]	port_id             can 端口索引 ID
 * @param[in]	node_id             接收节点 ID
 * @param[in]	fit_id              过滤器 ID
 * @param[in]	fit_mask            过滤器屏蔽位
 * @param[in]	queue               消息接收队列
 * @return      bool                执行结果
 */
extern bool can_controller_add_node_filter_static(uint8_t port_id, uint32_t node_id, uint32_t fit_id, uint32_t fit_mask, aos_queue_t* const queue);
/**
 * @brief       添加接收节点（指定消息接收队列）
 * @param[in]	port_id             can 端口索引 ID
 * @param[in]	node_id             接收节点 ID
 * @param[in]	queue               消息接收队列
 * @return      bool                执行结果
 */
extern bool can_controller_add_node_static(uint8_t port_id, uint32_t node_id, aos_queue_t* const queue);
/**
 * @brief       添加接收节点
 * @param[in]	port_id             can 端口索引 ID
 * @param[in]	node_id             接收节点 ID
 * @param[in]	queue_depth         消息接收队列深度
 * @return      aos_queue_t*        消息接收队列 handle
 */
extern aos_queue_t* can_controller_add_node(uint8_t port_id, uint32_t node_id, uint8_t queue_depth);
/**
 * @brief       通过节点id删除之前注册关联的所有消息邮箱,这些邮箱将被释放以作它用
 * @param[in]	port_id             can 端口索引 ID
 * @param[in]	node_id             接收节点 ID
 * @return      bool                执行结果
 */
extern bool can_controller_del_node_byId(uint8_t port_id, uint32_t node_id);
/**
 * @brief       发送SDO数据包
 * @param[in]	port_id             can 端口索引
 * @param[in]	node_id             发送节点 id
 * @param[in]	cmd                 cmd 字段
 * @param[in]	index               index 字段
 * @param[in]	data                数据字段
 * @return      bool                发送结果
 */
 extern bool can_control_send_sdo_frame(uint8_t port_id, uint32_t node_id, uint8_t cmd, uint16_t index, uint8_t subindex, uint32_t data);

extern void modify_can_cantroller_bitrate(uint8_t port_id, uint32_t baudRate);
extern void get_bus_error_cnt(uint8_t port_id, uint8_t *txErrBuf, uint8_t *rxErrBuf, uint32_t *tx_fail_cnts, uint16_t *tx_fail_rate);
extern bool get_flexcan_rx_overflow(void);
#endif